package com.link.base.base.apimiddle.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.link.base.base.apimiddle.dao.mybatis.mapper.ApiMiddleMapper;
import com.link.base.base.apimiddle.model.ApiMiddle;
import com.link.base.base.interinfo.model.InterInfo;
import com.link.base.base.interverify.dao.mybatis.mapper.InterLogMapper;
import com.link.base.base.interverify.model.InterLog;
import com.link.core.basic.controller.BasicControllerException;
import com.link.core.basic.dao.mapper.BasicMapper;
import com.link.core.basic.interceptor.SecurityInterceptor;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.basic.service.BasicServiceImpl;
import com.link.core.basic.service.KeyGenerateService;
import com.link.core.cllog.LCLogger;
import com.link.core.kafka.KafkaTemplateFacotry;
import com.link.core.kafka.conf.KafkaEnv;
import com.link.core.util.DateUtil;
import com.link.core.util.StringUtils;
import com.link.core.util.UserUtil;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * &comments&
 *
 * @author zhangmin
 * @date 2019-07-03
 */
@Service
public class ApiMiddleServiceImpl extends BasicServiceImpl<ApiMiddle> implements ApiMiddleService {

    @Resource
    private KeyGenerateService keyGenerateService;

    @Resource
    private ApiMiddleMapper apiMiddleMapper;

    @Resource
    private InterLogMapper interLogMapper;

    private static final String AC_CATERING_TOPIC = "ac_catering_topic";

    @Resource
    private RestTemplate restTemplate;

    @Override
    public BasicMapper<ApiMiddle> getBasicMapper() {
        return apiMiddleMapper;
    }

    @Override
    public void processData(List<ApiMiddle> apiMiddleList) throws Exception {
        for (ApiMiddle apiMiddle : apiMiddleList) {
            String url = "http://" + apiMiddle.getModule() + apiMiddle.getRequestUrl();
            ResponseEntity<Map> response = null;
            Date startTime = new Date();
            String startTimeStr = DateUtil.dateToStr(startTime, "yyyy-MM-dd HH:mm:ss");
            HttpHeaders headers = new HttpHeaders();
            String token = SecurityInterceptor.internal_token.get();
            headers.add("INNERTOKEN", token);
            HttpEntity entity = new HttpEntity<Object>(apiMiddle.getMessage(), headers);
            LCLogger.info().withMessage("请求接口前日志").flush();
            String requestMethod = apiMiddle.getRequestMethod();
            if ("POST".equalsIgnoreCase(requestMethod)) {
                response = restTemplate.exchange(url, HttpMethod.POST, entity, Map.class);
            }
            if ("GET".equalsIgnoreCase(requestMethod)) {
                response = restTemplate.exchange(url, HttpMethod.GET, entity, Map.class);
            }
            if ("HEAD".equalsIgnoreCase(requestMethod)) {
                response = restTemplate.exchange(url, HttpMethod.HEAD, entity, Map.class);
            }
            if ("PUT".equalsIgnoreCase(requestMethod)) {
                response = restTemplate.exchange(url, HttpMethod.PUT, entity, Map.class);
            }
            if ("DELETE".equalsIgnoreCase(requestMethod)) {
                response = restTemplate.exchange(url, HttpMethod.DELETE, entity, Map.class);
            }
            LCLogger.info().withMessage("请求接口后日志").flush();
            Date endTime = new Date();
            String endTimeStr = DateUtil.dateToStr(endTime, "yyyy-MM-dd HH:mm:ss");
            // 保存日志
            InterLog interLog = new InterLog();
            Long id = keyGenerateService.keyGenerate();
            interLog.setId(id);
            if (response == null) {
                interLog.setResponseBody(null);
                interLog.setProcessStatus(null);
            } else {
                //获取返回状态
                Map returnContent = response.getBody();
                interLog.setResponseBody(JSONObject.toJSONString(returnContent));
                interLog.setProcessStatus(response.getStatusCodeValue() + "");
                LCLogger.info().withMessage("请求配置接口返回信息"
                        + JSONObject.toJSONString(returnContent)).flush();
            }
            // 1、根据同步响应码是否为200，判断是否同步成功
            if ("200".equals(interLog.getProcessStatus())) {
                apiMiddle.setStatus("Succeeded");
            } else {
                apiMiddle.setStatus("Failed");
            }
            apiMiddle.setStartDate(startTimeStr);
            apiMiddle.setEndDate(endTimeStr);
            apiMiddleMapper.update(apiMiddle);

            // 2、将接口调用信息保存到接口调用信息表中
            try {
                interLog.setEndTime(startTimeStr);
                interLog.setStartTime(endTimeStr);
                interLog.setParams(apiMiddle.getMessage());
                interLog.setHeadId(apiMiddle.getId());
                LCLogger.info().withMessage("记录接口日志信息" + JSONObject.toJSONString(interLog)).flush();
                interLogMapper.insert(interLog);
            } catch (Exception e) {
                LCLogger.error().withMessage("记录接口日志报错" + e).flush();
                LCLogger.withException(e);
            }
        }
    }

    @Override
    public void dataAccess(Object data, InterInfo interInfo) throws Exception {
        String interCode = interInfo.getInterCode();
        if ("FX_ZHLS_0001".equals(interCode) || "FX_ZHLS_0002".equals(interCode) || "MD_ZHLS_001".equals(interCode)) {
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(data));
            if (jsonObject == null || jsonObject.isEmpty()) {
                throw new BasicControllerException("报文为空！");
            }
            sendTerminal(jsonObject, interInfo);
        }
    }

    private void sendTerminal(JSONObject jsonObject, InterInfo interInfo) throws Exception {
        ApiMiddle apiMiddle = new ApiMiddle();
        String interCode = interInfo.getInterCode();
        apiMiddle.setInterfaceName(interInfo.getInterName());
        apiMiddle.setInterfaceId(interInfo.getInterCode());
        apiMiddle.setStatus("New");
        JSONArray arrays = jsonObject.getJSONArray("items");
        List<JSONObject> list = JSONObject.parseArray(arrays.toJSONString(), JSONObject.class);
        apiMiddle.setModule("Terminal");
        for (JSONObject jsonObject1 : list) {
            apiMiddle.setId(this.keyGenerateService.keyGenerate());
            apiMiddle.setMessage(jsonObject1.toJSONString());
            apiMiddleMapper.insert(apiMiddle);
            sendCateringData(apiMiddle);
        }
    }


    @Override
    public List<ApiMiddle> queryByInterCode(List<String> interCodes) {
        return apiMiddleMapper.queryByInterCode(interCodes);
    }

    /**
     * 消息队列处理数据
     *
     * @param apiMiddle
     */
    @Override
    public void sendCateringData(ApiMiddle apiMiddle) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("user_name", UserUtil.getUser().getUsername());
        jsonObject.put("apiMiddle", apiMiddle);
        try {
            if (KafkaEnv.isEnabled()) {
                try {
                    KafkaTemplateFacotry.send(AC_CATERING_TOPIC, jsonObject.toString());
                } catch (Exception e) {
                    LCLogger.withException(e.getMessage());
                }
            } else {
                throw new Exception("kafka server is not avilabel!");
            }
        } catch (Exception e) {
            LCLogger.withException(e.getMessage());
            throw new BasicServiceException("餐饮终端添加kafka队列失败，终端ID：" + apiMiddle.getId() + e.getMessage());
        }
    }

    @Override
    public ApiMiddle queryLastRecordByModule(ApiMiddle apiMiddle) throws Exception {
        if (StringUtils.isBlank(apiMiddle.getModule())) {
            throw new BasicServiceException("参数module不能为空");
        }
        return apiMiddleMapper.queryLastRecordByModule(apiMiddle);
    }

    @Override
    public void afterExecutedUpdate(ApiMiddle apiMiddle) throws Exception {
        apiMiddleMapper.afterExecutedUpdate(apiMiddle);
    }
}

